// Copyright (C) Calum Grant 2008

#include "cppscript"
#include "dynamic/extensions.hpp"
#include "wrap_cpp_container.hpp"

#include <list>

static_call( register_pickle_type( cmp_list, list() ) );

using internal::nonroot_var;


namespace
{
	struct list_traits
	{
		typedef nonroot_var value_type;

		typedef std::list<value_type, dynamic::allocator<value_type> > container;

		static var key(const nonroot_var & i) 
		{ 
			return i.get();
		}

		static var value(const nonroot_var & i) 
		{ 
			return i.get(); 
		}

		static var deref(const nonroot_var & i)
		{ 
			return i.get(); 
		}

		static void mark_reachable(const nonroot_var & i, gc::garbage_collector & gc)
		{
			i.ref().impl().mark_reachable(gc);
		}

		static const var_cmp_index comparison_index = cmp_list;

		static const var & to_value(const var & v) 
		{ 
			return v; 
		}

		static var back(const container & c) 
		{ 
			return c.back().get(); 
		}

		static var front(const container & c) 
		{ 
			return c.front().get(); 
		}

		static void pop_back(container & c) 
		{ 
			c.pop_back();
		}

		static void pickle(pickler & p, const nonroot_var & i)
		{
			p.write_object(i.ref());
		}

		static var unpickle(unpickler & p)
		{
			return p.read_object();
		}

		static const char * class_name() 
		{ 
			return "list";
		}

		static const char * iterator_class_name()
		{ 
			return "list::iterator";
		}
	};
}

namespace dynamic
{
	namespace types
	{
		/// Implements a list variable.
		/** \ingroup impl */
		typedef dynamic::internal::wrap_list_container<list_traits> list_impl;
	}
}


var dynamic::list()
{
	return new types::list_impl();
}


var dynamic::list(const var & i0)
{
	return list()(i0);
}


var dynamic::list(const var & i0, const var & i1)
{
	return list(i0)(i1);
}


var dynamic::list(const var & i0, const var & i1, const var & i2)
{
	return list(i0)(i1)(i2);
}


var dynamic::list(const var & i0, const var & i1, const var & i2, const var & i3)
{
	return list(i0)(i1)(i2)(i3);
}


var dynamic::list(const var & i0, const var & i1, const var & i2, const var & i3, const var & i4)
{
	return list(i0)(i1)(i2)(i3)(i4);
}


var dynamic::list(const var & i0, const var & i1, const var & i2, const var & i3, const var & i4, const var & i5)
{
	return list(i0)(i1)(i2)(i3)(i4)(i5);
}


var dynamic::list(const var & i0, const var & i1, const var & i2, const var & i3, const var & i4, const var & i5, const var & i6)
{
	return list(i0)(i1)(i2)(i3)(i4)(i5)(i6);
}


var dynamic::list(const var & i0, const var & i1, const var & i2, const var & i3, const var & i4, const var & i5, const var & i6, const var & i7)
{
	return list(i0)(i1)(i2)(i3)(i4)(i5)(i6)(i7);
}


var dynamic::list(const var & i0, const var & i1, const var & i2, const var & i3, const var & i4, const var & i5, const var & i6, const var & i7, const var & i8)
{
	return list(i0)(i1)(i2)(i3)(i4)(i5)(i6)(i7)(i8);
}


var dynamic::list(const var & i0, const var & i1, const var & i2, const var & i3, const var & i4, const var & i5, const var & i6, const var & i7, const var & i8, const var & i9)
{
	return list(i0)(i1)(i2)(i3)(i4)(i5)(i6)(i7)(i8)(i9);
}


var dynamic::list_from(const var & container)
{
	var l = list();
	foreach(i, container) l.push_back(i);
	return l;
}
